package com.bjb.vr.common.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjb.vr.common.ao.OptCusDevAo;
import com.bjb.vr.common.ao.OptCusImportDevDetailAo;
import com.bjb.vr.common.ao.ResDeviceAo;
import com.bjb.vr.common.constant.ThreadLocalConstant;
import com.bjb.vr.common.dto.ResContent;
import com.bjb.vr.common.dto.ResDevice;
import com.bjb.vr.common.dto.ResGroup;
import com.bjb.vr.common.dto.ResGroupRef;
import com.bjb.vr.common.exception.CommonException;
import com.bjb.vr.common.mapper.ResDeviceMapper;
import com.bjb.vr.common.mapper.ResGroupMapper;
import com.bjb.vr.common.mapper.ResGroupRefMapper;
import com.bjb.vr.common.utils.ThreadLocalUtil;
import com.bjb.vr.common.vo.UmsAccountVo;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
* @author caihaibo
* @description 针对表【res_group(房间表)】的数据库操作Service实现
* @createDate 2022-03-22 10:49:59
*/
@Service
public class OptCusDevService extends ServiceImpl<ResGroupMapper, ResGroup>{


    @Autowired
    ResDeviceMapper resDeviceMapper;
    @Autowired
    ResGroupMapper resGroupMapper;
    @Autowired
    ResGroupRefMapper resGroupRefMapper;



    //分组管理-设备组查询列表
    public IPage<ResDevice> queryGroupDevList(OptCusDevAo cusDevAo) {
        Assert.notNull(cusDevAo.getGroupId(), "分组Id不能为空！");
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);

        MPJLambdaWrapper<ResDevice> joinQueryWrapper = new MPJLambdaWrapper<>();
        joinQueryWrapper
                .select(ResDevice::getId)
                .select(ResDevice::getUdid)
                .select(ResDevice::getDevName)
                .select(ResDevice::getMode)
                .select(ResDevice::getTotalMem)
                .select(ResDevice::getDevModel)
                .innerJoin(ResGroupRef.class,ResGroupRef::getDevId,ResDevice::getId)
                .innerJoin(ResGroup.class,ResGroup::getId,ResGroupRef::getGroupId);
        joinQueryWrapper.eq(ResGroup::getId,cusDevAo.getGroupId());
        IPage<ResDevice> resDeviceIPage = resDeviceMapper.selectPage(new Page<>(cusDevAo.getCurrent(), cusDevAo.getSize()), joinQueryWrapper);

        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, false);
        return resDeviceIPage;
    }


    //获取租户设备列表
    public IPage<ResDevice> queryTenantDevList(ResDeviceAo resDeviceAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);

        MPJLambdaWrapper<ResDevice> joinQueryWrapper = new MPJLambdaWrapper<>();
        joinQueryWrapper
                .select(ResDevice::getId)
                .select(ResDevice::getUdid)
                .select(ResDevice::getDevName);

        joinQueryWrapper.eq(ResDevice::getTenantId,resDeviceAo.getTenantId());
        joinQueryWrapper.like(StringUtils.isNotBlank(resDeviceAo.getUdid()), ResDevice::getUdid,resDeviceAo.getUdid());
        IPage<ResDevice> resDeviceIPage = resDeviceMapper.selectPage(new Page<>(resDeviceAo.getCurrent(), resDeviceAo.getSize()), joinQueryWrapper);

        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, false);
        return resDeviceIPage;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public boolean addGroupDev(OptCusDevAo cusDevAo){
        Assert.notNull(cusDevAo.getGroupId(),"设备分组id不能为空");
        Assert.notNull(cusDevAo.getTenantId(),"租户id不能为空");
        Assert.notNull(cusDevAo.getUdid(),"设备唯一标识不能为空");
        Assert.notNull(cusDevAo.getDevName(),"请输入设备名称");

        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        LambdaQueryWrapper<ResDevice> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ResDevice::getUdid,cusDevAo.getUdid());
        int count = resDeviceMapper.selectCount(lambdaQueryWrapper);
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, false);
        if(count > 0){
            throw new CommonException("已存在该udid的设备!");
        }


        UmsAccountVo umsAccountVo = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
        umsAccountVo.setTempTenantId(cusDevAo.getTenantId());

        ResDevice resDevice = new ResDevice();
        resDevice.setUdid(cusDevAo.getUdid());
        resDevice.setDevName(cusDevAo.getDevName());
        resDevice.setMode(cusDevAo.getMode());
        resDevice.setTotalMem(cusDevAo.getTotalMem());
        resDevice.setDevModel(cusDevAo.getDevModel());
        resDevice.setGmtCreate(LocalDateTime.now());
        resDeviceMapper.insert(resDevice);

        ResGroupRef resGroupRef = new ResGroupRef();
        resGroupRef.setGroupId(cusDevAo.getGroupId());
        resGroupRef.setTenantId(cusDevAo.getTenantId());
        resGroupRef.setDevId(resDevice.getId());
        resGroupRef.setDevUdid(resDevice.getUdid());
        resGroupRef.setGmtCreate(LocalDateTime.now());
        resGroupRefMapper.insert(resGroupRef);

        umsAccountVo.setTempTenantId("");
        return true;
    }


    public boolean updateGroupDev(OptCusDevAo cusDevAo){
        Assert.notNull(cusDevAo.getDevId(), "分组设备Id不能为空！");
        Assert.notNull(cusDevAo.getDevName(),"设备名不能为空");

        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);

        ResDevice resDevice = new ResDevice();
        resDevice.setId(cusDevAo.getDevId());
        resDevice.setDevName(cusDevAo.getDevName());

        boolean result = (resDeviceMapper.updateById(resDevice) == 1);
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, false);
        return result;
    }


    @Transactional(propagation = Propagation.REQUIRED)
    public boolean deleteGroupDev(OptCusDevAo cusDevAo){
        Assert.notNull(cusDevAo.getDevId(), "设备Id不能为空！");
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);

        LambdaQueryWrapper<ResGroupRef> lambdaQueryWrapper = Wrappers.lambdaQuery(ResGroupRef.class);
        lambdaQueryWrapper.eq(ResGroupRef::getDevId,cusDevAo.getDevId());
        int count = resGroupRefMapper.delete(lambdaQueryWrapper);
        if(count ==1) {
            resDeviceMapper.deleteById(cusDevAo.getDevId());
        }
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, false);
        return true;
    }


    /**
     * 客户配置管理-新增设备
     * @param resDeviceAo
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public boolean addTenantSingleDev(ResDeviceAo resDeviceAo){
        Assert.notNull(resDeviceAo.getGroupId(),"设备分组id不能为空");
        Assert.notNull(resDeviceAo.getTenantId(),"客户tentantId不能为空");
        Assert.notNull(resDeviceAo.getUdid(),"设备唯一标识不能为空");
        Assert.notNull(resDeviceAo.getDevName(),"请输入设备名称");
        Assert.notNull(resDeviceAo.getDevModel(),"请选择设备型号");

        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        LambdaQueryWrapper<ResDevice> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ResDevice::getUdid,resDeviceAo.getUdid());
        int count = resDeviceMapper.selectCount(lambdaQueryWrapper);
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, false);
        if(count > 0){
            throw new CommonException("已存在该udid的设备!");
        }

        UmsAccountVo umsAccountVo = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
        umsAccountVo.setTempTenantId(resDeviceAo.getTenantId());

        ResDevice resDevice = new ResDevice();
        resDevice.setUdid(resDeviceAo.getUdid());
        resDevice.setDevName(resDeviceAo.getDevName());
        resDevice.setMode(resDeviceAo.getMode());
        resDevice.setDevModel(resDeviceAo.getDevModel());
        resDevice.setTotalMem(resDeviceAo.getTotalMem());
        resDevice.setSdTotalMem(resDeviceAo.getSdTotalMem());
        resDevice.setGmtCreate(LocalDateTime.now());
        resDeviceMapper.insert(resDevice);

        ResGroupRef resGroupRef = new ResGroupRef();
        resGroupRef.setGroupId(resDeviceAo.getGroupId());
        resGroupRef.setTenantId(resDeviceAo.getTenantId());
        resGroupRef.setDevId(resDevice.getId());
        resGroupRef.setDevUdid(resDevice.getUdid());
        resGroupRef.setGmtCreate(LocalDateTime.now());
        resGroupRefMapper.insert(resGroupRef);

        umsAccountVo.setTempTenantId("");
        return true;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public boolean importBatchDev (String tenantId, MultipartFile file) throws IOException {
        Assert.notNull(file,"导入文件不能为空");

        //1.1.根据Excel文件创建工作簿
        Workbook wb = new XSSFWorkbook(file.getInputStream());
        //1.2.获取Sheet
        Sheet sheet = wb.getSheetAt(0);//参数：索引
        //1.3.获取Sheet中的每一行，和每一个单元格
        //2.获取设备数据列表
        List<OptCusImportDevDetailAo> list = new ArrayList<>();
        for (int rowNum = 1; rowNum <= sheet.getLastRowNum(); rowNum++) {
            Row row = sheet.getRow(rowNum);//根据索引获取每一个行
            Object[] values = new Object[row.getLastCellNum()];
            for (int cellNum = 0; cellNum < row.getLastCellNum(); cellNum++) {
                Cell cell = row.getCell(cellNum);
                Object value = getCellValue(cell);
                values[cellNum] = value;
            }
            OptCusImportDevDetailAo user = new OptCusImportDevDetailAo(values);
            list.add(user);
        }
        //3.批量保存
        for (OptCusImportDevDetailAo optCusImportDevAo: list) {

            ResDevice resDevice = new ResDevice();
            resDevice.setUdid(optCusImportDevAo.getUdid());
            resDevice.setTenantId(tenantId);
            resDevice.setDevName(optCusImportDevAo.getDevName());
            resDevice.setMode(optCusImportDevAo.getMode());
            resDevice.setTotalMem(optCusImportDevAo.getTotalMem());
            resDevice.setDevModel(optCusImportDevAo.getDevModel());
            resDevice.setGmtCreate(LocalDateTime.now());
            resDeviceMapper.insert(resDevice);

            LambdaQueryWrapper<ResGroup> lambdaQueryWrapper = Wrappers.lambdaQuery(ResGroup.class);
            lambdaQueryWrapper.eq(ResGroup::getGroupName,optCusImportDevAo.getGroupName());
            lambdaQueryWrapper.eq(ResGroup::getTenantId,tenantId);
            ResGroup resGroup = resGroupMapper.selectOne(lambdaQueryWrapper);
            if(resGroup!=null) {
                ResGroupRef resGroupRef = new ResGroupRef();
                resGroupRef.setGroupId(resGroup.getId());
                resGroupRef.setTenantId(tenantId);
                resGroupRef.setDevId(resDevice.getId());
                resGroupRef.setDevUdid(resDevice.getUdid());
                resGroupRef.setGmtCreate(LocalDateTime.now());
                resGroupRefMapper.insert(resGroupRef);
            }else{
                throw new CommonException("未找到相应租户的设备分组");
            }
        }
        return true;
    }

    public static Object getCellValue(Cell cell) {
        //1.获取到单元格的属性类型
        CellType cellType = cell.getCellType();
        //2.根据单元格数据类型获取数据
        Object value = null;
        switch (cellType) {
            case STRING:
                value = cell.getStringCellValue();
                break;
            case BOOLEAN:
                value = cell.getBooleanCellValue();
                break;
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    //日期格式
                    value = cell.getDateCellValue();
                } else {
                    //数字
                    value = cell.getNumericCellValue();
                }
                break;
            default:
                break;
        }
        return value;
    }

}




